package com.enjoyor.soa.traffic.util.helper;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

/**
 * @author 周宏伟
 * @date 2017年5月1日
 * @email zhouhongwei@enjoyor.net
 * @description 反射帮助类
 */
public class ReflectHelper {

	/**
	 * Map转对象
	 * @param map
	 * @param beanClass
	 * @return
	 */
	public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
		if (map == null) {
			return null;
		}
		T bean = null;
		try {
			bean = (T) beanClass.newInstance();
			Field[] fields = bean.getClass().getDeclaredFields();
			for (Field field : fields) {
				int modifier = field.getModifiers();
				if (Modifier.isStatic(modifier) || Modifier.isFinal(modifier)) {
					continue;
				}
				field.setAccessible(true);
				field.set(bean, map.get(field.getName()));
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return bean;
	}

	/**
	 * 对象转Map
	 * @param object
	 * @return
	 */
	public static Map<String, Object> beanToMap(Object bean) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			Class<?> beanClass = bean.getClass();
			for (Field field : beanClass.getDeclaredFields()) {
				String fieldName = field.getName();
				for (Method method : beanClass.getMethods()) {
					try {
						if ((Pattern.matches("get(\\w+)", method.getName()) || Pattern.matches("is(\\w+)", method.getName())) && method.getParameterTypes().length == 0 && method.getDeclaringClass() != Object.class) {
							Pattern pattern = Pattern.matches("get(\\w+)", method.getName()) ? Pattern.compile("get(\\w+)") : Pattern.compile("is(\\w+)");
							String param = pattern.matcher(method.getName()).replaceAll("$1");
							if (fieldName.equalsIgnoreCase(param)) {
								Object ret = method.invoke(bean);
								if (ret != null) {
									map.put(fieldName, ret);
								}
								break;
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 常规对象转换
	 * @param object
	 * @param beanClass
	 * @return
	 */
	public static <T> T beanToBean(Object bean, Class<T> beanClass) {
		if (bean == null) {
			return null;
		}
		Map<Class<?>, Class<?>> map = new HashMap<>();
		map.put(bean.getClass(), beanClass);
		return beanToBean(bean, beanClass, map);
	}

	/**
	 * 综合对象转换
	 * @param bean
	 * @param beanClasses
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T beanToBean(Object bean, Map<Class<?>, Class<?>> beanClasses) {
		if (bean == null) {
			return null;
		} else if (beanClasses != null && beanClasses.containsKey(bean.getClass())) {
			return beanToBean(bean, (Class<T>) beanClasses.get(bean.getClass()), beanClasses);
		}
		return null;
	}

	/**
	 * 嵌套对象转换
	 * @param object
	 * @param beanClass
	 * @param beanClasses
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static <T> T beanToBean(Object bean, Class<T> beanClass, Map<Class<?>, Class<?>> beanClasses) {
		if (bean == null) {
			return null;
		}
		Map<String, Object> map = beanToMap(bean);
		if (map == null) {
			return null;
		}
		if (beanClasses == null) {
			beanClasses = new HashMap<>();
		}
		beanClasses.put(bean.getClass(), beanClass);
		Map<String, Object> result = new HashMap<>();
		for (Iterator<Entry<String, Object>> iterator = map.entrySet().iterator(); iterator.hasNext();) {
			Entry<String, Object> item = iterator.next();
			if (item.getValue() != null && beanClasses != null && beanClasses.containsKey(item.getValue().getClass())) {
				result.put(item.getKey(), beanToBean(item.getValue(), beanClasses.get(item.getValue().getClass())));
			} else if (item.getValue() != null && item.getValue() instanceof List) {
				result.put(item.getKey(), listToList((List) item.getValue(), beanClasses));
			} else {
				result.put(item.getKey(), item.getValue());
			}
		}
		return mapToBean(result, beanClass);
	}

	/**
	 * 常规集合转换
	 * @param source
	 * @param sourceClass
	 * @param targetClass
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static <T> List<T> listToList(List source, Class<T> targetClass) {
		List<T> result = new ArrayList<>();
		if (source != null && source.size() > 0) {
			Map<Class<?>, Class<?>> map = new HashMap<>();
			map.put(source.get(0).getClass(), targetClass);
			result = listToList(source, map);
		}
		return result;
	}

	/**
	 * 嵌套集合转换
	 * @param source
	 * @param targetClass
	 * @param beanClasses
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <T> List<T> listToList(List source, Map<Class<?>, Class<?>> beanClasses) {
		List<T> result = new ArrayList<>();
		if (source != null && source.size() > 0) {
			for (Iterator iterator = source.iterator(); iterator.hasNext();) {
				Object object = iterator.next();
				if (beanClasses != null && beanClasses.containsKey(object.getClass())) {
					try {
						Class<?> class1 = beanClasses.get(object.getClass());
						T target = (T) class1.newInstance();
						target = (T) beanToBean(object, class1, beanClasses);
						if (target != null) {
							result.add(target);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				} else {
					result.add((T) object);
				}
			}
		}
		return result;
	}
}
